#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <cstring>
#include <unistd.h>

void Usage()
{
    std::cout << "usage: ./Hello [ip] [port]\n" << std::endl;
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage();
        return 1;
    }

    uint16_t serverport = std::stoi(argv[2]);
    std::string serverip = argv[1];

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket fail\n");
        return 1;
    }

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = ntohs(serverport);
    server_addr.sin_addr.s_addr = inet_addr(serverip.c_str());

    int n = bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if (n < 0)
    {
        perror("bind fail\n");
        close(sockfd);
        return 1;
    }

    n = listen(sockfd, 10);
    if (n < 0)
    {
        perror("listen fail\n");
        close(sockfd);
        return 1;
    }

    while (true)
    {
        struct sockaddr_in client_addr;
        socklen_t len;
        int client_fd = accept(sockfd, (struct sockaddr*)&client_addr, &len);
        if (client_fd < 0)
        {
            perror("accept fail\n");
            continue;
        }

        char input_buffer[1024 * 10];
        ssize_t m = read(client_fd, input_buffer, sizeof(input_buffer) - 1);
        if (m < 0)
        {
            perror("read fail\n");
            continue;
        }
        input_buffer[m] = 0;
        std::cout << "[Request]" << input_buffer << std::endl;
        
        char buffer[1024];
        std::string hello = "Mifan: hello world";
        sprintf(buffer, "HTTP/1.0 200 OK\nContent-Length:%ld\nContent-Type:text/plain\n\n%s", hello.size(), hello.c_str());
        n = write(client_fd, buffer, strlen(buffer));
        if (n < 0)
        {
            perror("write fail\n");
            continue;
        }
        close(client_fd);
    }
    close(sockfd);
    return 0;
}